package app.geobeans.cn.sockettest;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;

import com.alibaba.fastjson.JSON;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ghx on 2016/12/14.
 */
public class MessageService extends Service {
    private static final String TAG = MessageService.class.getSimpleName();
    public static String MESSAGE_SERVER = "10.0.0.177";
    public static int MESSAGE_PORT = 2020;

    private static Socket mSocket;
    private static boolean RUNNING = true;
    private InputStream mInput;
    private OutputStream mOutstream;
    private SocketThread mThread;
    private MessageServiceBinder mLocalBinder;
    private PowerManager.WakeLock wakeLock = null;

    @Override
    public IBinder onBind(Intent intent) {
        return mLocalBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        acquireWakeLock();
        mLocalBinder = new MessageServiceBinder();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");
        acquireWakeLock();
        initSocket();
//        SocketThread mSocketThread = new SocketThread(this);
//        mSocketThread.isRun = true;
//        mSocketThread.start();

        return START_STICKY;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        if (mSocket != null) {
            try {
                mInput.close();
                mInput = null;
                mOutstream.close();
                mOutstream = null;
                mSocket.close();
                mSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void initSocket() {
        if (mSocket == null) {
            mThread = new SocketThread();
            mThread.start();
        }
    }

    //获取电源锁，保持该服务在屏幕熄灭时仍然获取CPU时，保持运行
    private void acquireWakeLock() {
        if (null == wakeLock) {
            PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MessageService");
            if (null != wakeLock) {
                wakeLock.acquire();
            }
        }
    }

    //释放设备电源锁
    private void releaseWakeLock() {
        if (null != wakeLock) {
            wakeLock.release();
            wakeLock = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        releaseWakeLock();

        stopForeground(true);

    }

    /**
     * 发送消息
     *
     * @param msg
     * @param msgData
     */
    synchronized void sendMessage(String msg, String msgData) {
        Log.e(TAG, "消息发送:" + msg + "," + msgData);
        try {
            if (mSocket == null || !mSocket.isConnected()) {
                Log.e(TAG, "未建立socket链接");
                mThread.connect();
            }
            byte[] bs = msg.getBytes();
            int jsonLen = bs.length;

            int msgLen = 0;
            if (!"".equals(msgData)) msgLen = msgData.getBytes().length;

            int totalLen = jsonLen + 2 + msgLen;

            byte[] tl = longToWord(totalLen, 4);
            byte[] jl = longToWord(jsonLen, 2);

            byte[] total = addAll(addAll(tl, jl), bs);

            if (!"".equals(msgData)) total = addAll(total, msgData.getBytes());

//            G.e("发送：" + new String(total));
            mOutstream.write(total);
            mOutstream.flush();

        } catch (Exception e) {
            Log.e(TAG, "消息发送出错");
            e.printStackTrace();
        }
    }

    /**
     * 将long型数据转换为word的字节数组（C/C++的无符号整数）
     */
    private byte[] longToWord(long value, int n) {

        byte[] data = new byte[n];
        int len = data.length;
        for (int i = 0; i < len; i++) {
            int j = len - i - 1;
            data[i] = (byte) (value >> (8 * j) & 0xff);
        }

        return data;
    }


    private byte[] addAll(byte[] array1, byte[] array2) {
        if (array1 == null) {
            String str2 = new String(array2);
            return str2.getBytes();
        } else if (array2 == null) {
            String str1 = new String(array1);
            return str1.getBytes();
        }
        byte[] joinedArray = new byte[array1.length + array2.length];
        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
        return joinedArray;
    }

    /*
    * ******************************内部类****************************
    * */
    public class MessageServiceBinder extends Binder {
        public MessageService getService() {
            return MessageService.this;
        }

    }


    /**
     * socket接收线程
     * Created by PuJuntao on 2016/11/29.
     */
    public class SocketThread extends Thread {


        /**
         * 连接socket服务器
         */
        void connect() {
            try {
                Log.i(TAG, "连接中……");
                mSocket = new Socket(MESSAGE_SERVER, MESSAGE_PORT);
                mSocket.setKeepAlive(true);
                mInput = mSocket.getInputStream();
                mOutstream = mSocket.getOutputStream();
//            mSocket = new Socket("123.183.161.195", 2020);
                Log.i(TAG, "连接成功");
                socketLogin();
            } catch (IOException e) {
                e.printStackTrace();
                Log.i(TAG, "连接服务器错误");
            }
        }

        /**
         * 实时接受数据
         */
        @Override
        public void run() {
            try {
                connect();

                Log.e(TAG, "数据准备接收");
                while (RUNNING ) {

//                if (mSocket != null && mSocket.isConnected()) {
                    if (!mSocket.isInputShutdown() && mInput.available() > 0 ) {
                        int totalCount = getLength(mInput, 4);
                        if (totalCount > 0) {

                            int jsonCount = getLength(mInput, 2);

                            byte[] datas = new byte[totalCount];
                            mInput.read(datas);
                            Log.e(TAG, "总数据：" + new String(datas));
                        }
                    } else {
                        mInput = mSocket.getInputStream();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "数据接收错误");
                e.printStackTrace();
            }

        }

        private void socketLogin() {
            Map<String, Object> msg = new HashMap<>();
            msg.put("Command", "LOGIN");
            msg.put("UserID", "ff808081260e7bd6012640f02b40411a");
            msg.put("UserType", "NORMAL");

            sendMessage(JSON.toJSONString(msg), "");
        }


        /**
         * 获取is中的前n位字节表示的数字
         *
         * @param is
         * @param n
         * @return
         */
        private int getLength(InputStream is, int n) throws Exception {
            if (n <= 0) {
                return 0;
            }
            byte[] bytes = new byte[n];
            is.read(bytes);
            int len = wordTolong(bytes);
            return len;
        }

        /**
         * 将word的字节数组（C/C++的无符号整数）转换为long型数据
         *
         * @param bs
         * @return
         */
        private int wordTolong(byte[] bs) {
            int value = 0;
            if (bs == null || bs.length == 0) {
                return value;
            }
            int len = bs.length;
            for (int i = 0; i < len; i++) {
                int j = len - i - 1;
                value |= ((bs[i] & 0xff)) << (8 * j);
            }
            return value;
        }

        /**
         * 读取流中的数据，解析为json
         *
         * @param is
         * @param n
         * @return
         * @throws Exception
         */
        private String getJson(InputStream is, int n) throws Exception {
            if (n <= 0) {
                return "";
            }
            byte[] bytes = new byte[n];
            is.read(bytes);
            String json = new String(bytes);
            return json;
        }


    }


}
